/**
 * InputManager - 输入管理器类
 * 负责处理键盘和触摸输入事件，将输入转换为游戏动作
 */

export enum InputAction {
  JUMP = 'jump',
  SLIDE = 'slide',
  MOVE_LEFT = 'moveLeft',
  MOVE_RIGHT = 'moveRight',
  PAUSE = 'pause'
}

export enum KeyCode {
  SPACE = 'Space',
  ARROW_UP = 'ArrowUp',
  ARROW_DOWN = 'ArrowDown',
  ARROW_LEFT = 'ArrowLeft',
  ARROW_RIGHT = 'ArrowRight',
  ENTER = 'Enter',
  ESCAPE = 'Escape',
  KEY_W = 'KeyW',
  KEY_A = 'KeyA',
  KEY_S = 'KeyS',
  KEY_D = 'KeyD',
  KEY_P = 'KeyP'
}

export interface InputBinding {
  action: InputAction
  keys: KeyCode[]
  preventDefault?: boolean
}

export interface InputHandler {
  (action: InputAction, pressed: boolean): void
}

export interface TouchGesture {
  type: 'tap' | 'swipe' | 'hold'
  direction?: 'up' | 'down' | 'left' | 'right'
  startX: number
  startY: number
  endX?: number
  endY?: number
  duration: number
}

export interface TouchBinding {
  gesture: TouchGesture['type']
  direction?: TouchGesture['direction']
  action: InputAction
  minDistance?: number
  maxDuration?: number
}

export interface InputManagerOptions {
  element?: HTMLElement
  preventDefaultKeys?: KeyCode[]
  enableKeyRepeat?: boolean
  keyRepeatDelay?: number
  keyRepeatRate?: number
  enableTouch?: boolean
  touchSensitivity?: number
  swipeMinDistance?: number
  tapMaxDuration?: number
  holdMinDuration?: number
}

export class InputManager {
  private element: HTMLElement
  private bindings: Map<KeyCode, InputBinding> = new Map()
  private touchBindings: TouchBinding[] = []
  private handlers: Set<InputHandler> = new Set()
  private pressedKeys: Set<KeyCode> = new Set()
  private preventDefaultKeys: Set<KeyCode> = new Set()
  private enableKeyRepeat: boolean
  private keyRepeatDelay: number
  private keyRepeatRate: number
  private keyRepeatTimers: Map<KeyCode, number> = new Map()
  private isEnabled: boolean = true
  
  // 触摸相关属性
  private enableTouch: boolean
  // Touch sensitivity (reserved for future use)
  // private touchSensitivity: number
  private swipeMinDistance: number
  private tapMaxDuration: number
  private holdMinDuration: number
  private activeTouches: Map<number, { startX: number; startY: number; startTime: number }> = new Map()
  private touchTimers: Map<number, number> = new Map()

  // 绑定的事件处理器引用（用于正确移除事件监听器）
  private boundHandleKeyDown: (event: KeyboardEvent) => void
  private boundHandleKeyUp: (event: KeyboardEvent) => void
  private boundHandleTouchStart: (event: TouchEvent) => void
  private boundHandleTouchMove: (event: TouchEvent) => void
  private boundHandleTouchEnd: (event: TouchEvent) => void
  private boundHandleTouchCancel: (event: TouchEvent) => void

  constructor(options: InputManagerOptions = {}) {
    this.element = options.element || document.body
    this.enableKeyRepeat = options.enableKeyRepeat || false
    this.keyRepeatDelay = options.keyRepeatDelay || 500 // ms
    this.keyRepeatRate = options.keyRepeatRate || 50 // ms

    // 触摸相关配置
    this.enableTouch = options.enableTouch !== false // 默认启用
    // this.touchSensitivity = options.touchSensitivity || 1.0
    this.swipeMinDistance = options.swipeMinDistance || 50 // px
    this.tapMaxDuration = options.tapMaxDuration || 300 // ms
    this.holdMinDuration = options.holdMinDuration || 500 // ms

    // 创建绑定的事件处理器引用
    this.boundHandleKeyDown = this.handleKeyDown.bind(this)
    this.boundHandleKeyUp = this.handleKeyUp.bind(this)
    this.boundHandleTouchStart = this.handleTouchStart.bind(this)
    this.boundHandleTouchMove = this.handleTouchMove.bind(this)
    this.boundHandleTouchEnd = this.handleTouchEnd.bind(this)
    this.boundHandleTouchCancel = this.handleTouchCancel.bind(this)

    // 设置默认的阻止默认行为的按键
    if (options.preventDefaultKeys) {
      options.preventDefaultKeys.forEach(key => {
        this.preventDefaultKeys.add(key)
      })
    }

    // 设置默认按键绑定
    this.setupDefaultBindings()

    // 设置默认触摸绑定
    this.setupDefaultTouchBindings()

    // 绑定事件监听器
    this.bindEventListeners()
  }

  /**
   * 设置默认按键绑定
   */
  private setupDefaultBindings(): void {
    // 跳跃控制
    this.addBinding({
      action: InputAction.JUMP,
      keys: [KeyCode.SPACE, KeyCode.ARROW_UP, KeyCode.KEY_W],
      preventDefault: true
    })

    // 滑铲控制
    this.addBinding({
      action: InputAction.SLIDE,
      keys: [KeyCode.ARROW_DOWN, KeyCode.KEY_S],
      preventDefault: true
    })

    // 左移控制
    this.addBinding({
      action: InputAction.MOVE_LEFT,
      keys: [KeyCode.ARROW_LEFT, KeyCode.KEY_A],
      preventDefault: true
    })

    // 右移控制
    this.addBinding({
      action: InputAction.MOVE_RIGHT,
      keys: [KeyCode.ARROW_RIGHT, KeyCode.KEY_D],
      preventDefault: true
    })

    // 暂停控制
    this.addBinding({
      action: InputAction.PAUSE,
      keys: [KeyCode.KEY_P, KeyCode.ESCAPE],
      preventDefault: true
    })
  }

  /**
   * 设置默认触摸绑定
   */
  private setupDefaultTouchBindings(): void {
    if (!this.enableTouch) return

    // 点击跳跃
    this.addTouchBinding({
      gesture: 'tap',
      action: InputAction.JUMP,
      maxDuration: this.tapMaxDuration
    })

    // 向上滑动跳跃
    this.addTouchBinding({
      gesture: 'swipe',
      direction: 'up',
      action: InputAction.JUMP,
      minDistance: this.swipeMinDistance
    })

    // 向下滑动滑铲
    this.addTouchBinding({
      gesture: 'swipe',
      direction: 'down',
      action: InputAction.SLIDE,
      minDistance: this.swipeMinDistance
    })

    // 向左滑动左移
    this.addTouchBinding({
      gesture: 'swipe',
      direction: 'left',
      action: InputAction.MOVE_LEFT,
      minDistance: this.swipeMinDistance
    })

    // 向右滑动右移
    this.addTouchBinding({
      gesture: 'swipe',
      direction: 'right',
      action: InputAction.MOVE_RIGHT,
      minDistance: this.swipeMinDistance
    })

    // 长按暂停
    this.addTouchBinding({
      gesture: 'hold',
      action: InputAction.PAUSE,
      minDistance: 0
    })
  }

  /**
   * 绑定事件监听器
   */
  private bindEventListeners(): void {
    // 键盘事件
    this.element.addEventListener('keydown', this.boundHandleKeyDown)
    this.element.addEventListener('keyup', this.boundHandleKeyUp)
    
    // 触摸事件
    if (this.enableTouch) {
      this.element.addEventListener('touchstart', this.boundHandleTouchStart, { passive: false })
      this.element.addEventListener('touchmove', this.boundHandleTouchMove, { passive: false })
      this.element.addEventListener('touchend', this.boundHandleTouchEnd, { passive: false })
      this.element.addEventListener('touchcancel', this.boundHandleTouchCancel, { passive: false })
    }
    
    // 确保元素可以接收焦点
    if (this.element.tabIndex < 0) {
      this.element.tabIndex = 0
    }
  }

  /**
   * 解绑事件监听器
   */
  private unbindEventListeners(): void {
    this.element.removeEventListener('keydown', this.boundHandleKeyDown)
    this.element.removeEventListener('keyup', this.boundHandleKeyUp)
    
    if (this.enableTouch) {
      this.element.removeEventListener('touchstart', this.boundHandleTouchStart)
      this.element.removeEventListener('touchmove', this.boundHandleTouchMove)
      this.element.removeEventListener('touchend', this.boundHandleTouchEnd)
      this.element.removeEventListener('touchcancel', this.boundHandleTouchCancel)
    }
  }

  /**
   * 处理按键按下事件
   */
  private handleKeyDown(event: KeyboardEvent): void {
    if (!this.isEnabled) return

    const keyCode = event.code as KeyCode
    
    // 阻止默认行为
    if (this.preventDefaultKeys.has(keyCode)) {
      event.preventDefault()
    }

    // 检查是否已经按下（避免重复触发）
    const wasPressed = this.pressedKeys.has(keyCode)
    this.pressedKeys.add(keyCode)

    // 获取绑定的动作
    const binding = this.bindings.get(keyCode)
    if (binding) {
      if (binding.preventDefault) {
        event.preventDefault()
      }

      // 只在首次按下时触发动作
      if (!wasPressed) {
        this.triggerAction(binding.action, true)
        
        // 设置按键重复
        if (this.enableKeyRepeat) {
          this.setupKeyRepeat(keyCode, binding.action)
        }
      }
    }
  }

  /**
   * 处理按键释放事件
   */
  private handleKeyUp(event: KeyboardEvent): void {
    if (!this.isEnabled) return

    const keyCode = event.code as KeyCode
    this.pressedKeys.delete(keyCode)

    // 清除按键重复定时器
    this.clearKeyRepeat(keyCode)

    // 获取绑定的动作
    const binding = this.bindings.get(keyCode)
    if (binding) {
      if (binding.preventDefault) {
        event.preventDefault()
      }
      
      this.triggerAction(binding.action, false)
    }
  }

  /**
   * 设置按键重复
   */
  private setupKeyRepeat(keyCode: KeyCode, action: InputAction): void {
    // 清除现有的重复定时器
    this.clearKeyRepeat(keyCode)

    // 设置延迟后开始重复
    const delayTimer = window.setTimeout(() => {
      // 设置重复定时器
      const repeatTimer = window.setInterval(() => {
        if (this.pressedKeys.has(keyCode) && this.isEnabled) {
          this.triggerAction(action, true)
        } else {
          this.clearKeyRepeat(keyCode)
        }
      }, this.keyRepeatRate)

      this.keyRepeatTimers.set(keyCode, repeatTimer)
    }, this.keyRepeatDelay)

    this.keyRepeatTimers.set(keyCode, delayTimer)
  }

  /**
   * 清除按键重复定时器
   */
  private clearKeyRepeat(keyCode: KeyCode): void {
    const timer = this.keyRepeatTimers.get(keyCode)
    if (timer) {
      clearTimeout(timer)
      clearInterval(timer)
      this.keyRepeatTimers.delete(keyCode)
    }
  }

  /**
   * 处理触摸开始事件
   */
  private handleTouchStart(event: TouchEvent): void {
    if (!this.isEnabled || !this.enableTouch) return

    event.preventDefault()

    for (let i = 0; i < event.changedTouches.length; i++) {
      const touch = event.changedTouches[i]
      const touchId = touch.identifier
      
      this.activeTouches.set(touchId, {
        startX: touch.clientX,
        startY: touch.clientY,
        startTime: Date.now()
      })

      // 设置长按检测定时器
      const holdTimer = window.setTimeout(() => {
        this.handleHoldGesture(touchId)
      }, this.holdMinDuration)
      
      this.touchTimers.set(touchId, holdTimer)
    }
  }

  /**
   * 处理触摸移动事件
   */
  private handleTouchMove(event: TouchEvent): void {
    if (!this.isEnabled || !this.enableTouch) return

    event.preventDefault()
    // 触摸移动时不做特殊处理，主要在touchend时处理手势
  }

  /**
   * 处理触摸结束事件
   */
  private handleTouchEnd(event: TouchEvent): void {
    if (!this.isEnabled || !this.enableTouch) return

    event.preventDefault()

    for (let i = 0; i < event.changedTouches.length; i++) {
      const touch = event.changedTouches[i]
      const touchId = touch.identifier
      
      this.processTouchGesture(touchId, touch.clientX, touch.clientY)
      this.cleanupTouch(touchId)
    }
  }

  /**
   * 处理触摸取消事件
   */
  private handleTouchCancel(event: TouchEvent): void {
    if (!this.isEnabled || !this.enableTouch) return

    for (let i = 0; i < event.changedTouches.length; i++) {
      const touch = event.changedTouches[i]
      this.cleanupTouch(touch.identifier)
    }
  }

  /**
   * 处理长按手势
   */
  private handleHoldGesture(touchId: number): void {
    const touchData = this.activeTouches.get(touchId)
    if (!touchData) return

    // 查找匹配的长按绑定
    const holdBinding = this.touchBindings.find(binding => 
      binding.gesture === 'hold'
    )

    if (holdBinding) {
      this.triggerAction(holdBinding.action, true)
    }
  }

  /**
   * 处理触摸手势
   */
  private processTouchGesture(touchId: number, endX: number, endY: number): void {
    const touchData = this.activeTouches.get(touchId)
    if (!touchData) return

    const deltaX = endX - touchData.startX
    const deltaY = endY - touchData.startY
    const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY)
    const duration = Date.now() - touchData.startTime

    // 判断手势类型
    if (distance < this.swipeMinDistance && duration < this.tapMaxDuration) {
      // 点击手势
      this.handleTapGesture()
    } else if (distance >= this.swipeMinDistance) {
      // 滑动手势
      this.handleSwipeGesture(deltaX, deltaY, distance)
    }
  }

  /**
   * 处理点击手势
   */
  private handleTapGesture(): void {
    const tapBinding = this.touchBindings.find(binding => 
      binding.gesture === 'tap'
    )

    if (tapBinding) {
      this.triggerAction(tapBinding.action, true)
      // 立即触发释放事件
      setTimeout(() => {
        this.triggerAction(tapBinding.action, false)
      }, 50)
    }
  }

  /**
   * 处理滑动手势
   */
  private handleSwipeGesture(deltaX: number, deltaY: number, distance: number): void {
    // 确定滑动方向
    let direction: 'up' | 'down' | 'left' | 'right'
    
    if (Math.abs(deltaX) > Math.abs(deltaY)) {
      // 水平滑动
      direction = deltaX > 0 ? 'right' : 'left'
    } else {
      // 垂直滑动
      direction = deltaY > 0 ? 'down' : 'up'
    }

    // 查找匹配的滑动绑定
    const swipeBinding = this.touchBindings.find(binding => 
      binding.gesture === 'swipe' && 
      binding.direction === direction &&
      (!binding.minDistance || distance >= binding.minDistance)
    )

    if (swipeBinding) {
      this.triggerAction(swipeBinding.action, true)
      // 立即触发释放事件
      setTimeout(() => {
        this.triggerAction(swipeBinding.action, false)
      }, 50)
    }
  }

  /**
   * 清理触摸数据
   */
  private cleanupTouch(touchId: number): void {
    this.activeTouches.delete(touchId)
    
    const timer = this.touchTimers.get(touchId)
    if (timer) {
      clearTimeout(timer)
      this.touchTimers.delete(touchId)
    }
  }

  /**
   * 触发动作
   */
  private triggerAction(action: InputAction, pressed: boolean): void {
    this.handlers.forEach(handler => {
      try {
        handler(action, pressed)
      } catch (error) {
        console.error('Error in input handler:', error)
      }
    })
  }

  /**
   * 添加按键绑定
   */
  addBinding(binding: InputBinding): void {
    binding.keys.forEach(key => {
      this.bindings.set(key, binding)
      
      // 如果设置了阻止默认行为，添加到集合中
      if (binding.preventDefault) {
        this.preventDefaultKeys.add(key)
      }
    })
  }

  /**
   * 移除按键绑定
   */
  removeBinding(keyCode: KeyCode): void {
    this.bindings.delete(keyCode)
    this.preventDefaultKeys.delete(keyCode)
  }

  /**
   * 清除所有绑定
   */
  clearBindings(): void {
    this.bindings.clear()
    this.preventDefaultKeys.clear()
  }

  /**
   * 添加触摸绑定
   */
  addTouchBinding(binding: TouchBinding): void {
    this.touchBindings.push(binding)
  }

  /**
   * 移除触摸绑定
   */
  removeTouchBinding(gesture: TouchGesture['type'], direction?: TouchGesture['direction']): void {
    this.touchBindings = this.touchBindings.filter(binding => 
      !(binding.gesture === gesture && binding.direction === direction)
    )
  }

  /**
   * 清除所有触摸绑定
   */
  clearTouchBindings(): void {
    this.touchBindings = []
  }

  /**
   * 获取触摸绑定列表
   */
  getTouchBindings(): TouchBinding[] {
    return [...this.touchBindings]
  }

  /**
   * 添加输入处理器
   */
  addHandler(handler: InputHandler): void {
    this.handlers.add(handler)
  }

  /**
   * 移除输入处理器
   */
  removeHandler(handler: InputHandler): void {
    this.handlers.delete(handler)
  }

  /**
   * 清除所有处理器
   */
  clearHandlers(): void {
    this.handlers.clear()
  }

  /**
   * 检查按键是否被按下
   */
  isKeyPressed(keyCode: KeyCode): boolean {
    return this.pressedKeys.has(keyCode)
  }

  /**
   * 检查动作是否被激活
   */
  isActionActive(action: InputAction): boolean {
    for (const [keyCode, binding] of this.bindings) {
      if (binding.action === action && this.pressedKeys.has(keyCode)) {
        return true
      }
    }
    return false
  }

  /**
   * 获取当前按下的所有按键
   */
  getPressedKeys(): KeyCode[] {
    return Array.from(this.pressedKeys)
  }

  /**
   * 获取指定动作的绑定按键
   */
  getKeysForAction(action: InputAction): KeyCode[] {
    const keys: KeyCode[] = []
    for (const [keyCode, binding] of this.bindings) {
      if (binding.action === action) {
        keys.push(keyCode)
      }
    }
    return keys
  }

  /**
   * 启用输入管理器
   */
  enable(): void {
    this.isEnabled = true
  }

  /**
   * 禁用输入管理器
   */
  disable(): void {
    this.isEnabled = false
    this.pressedKeys.clear()
    this.keyRepeatTimers.forEach(timer => {
      clearTimeout(timer)
      clearInterval(timer)
    })
    this.keyRepeatTimers.clear()
  }

  /**
   * 检查是否启用
   */
  isInputEnabled(): boolean {
    return this.isEnabled
  }

  /**
   * 设置目标元素
   */
  setElement(element: HTMLElement): void {
    this.unbindEventListeners()
    this.element = element
    this.bindEventListeners()
  }

  /**
   * 获取目标元素
   */
  getElement(): HTMLElement {
    return this.element
  }

  /**
   * 模拟按键按下（用于测试）
   */
  simulateKeyDown(keyCode: KeyCode): void {
    const event = new KeyboardEvent('keydown', { code: keyCode })
    this.handleKeyDown(event)
  }

  /**
   * 模拟按键释放（用于测试）
   */
  simulateKeyUp(keyCode: KeyCode): void {
    const event = new KeyboardEvent('keyup', { code: keyCode })
    this.handleKeyUp(event)
  }

  /**
   * 重置所有状态
   */
  reset(): void {
    this.pressedKeys.clear()
    this.keyRepeatTimers.forEach(timer => {
      clearTimeout(timer)
      clearInterval(timer)
    })
    this.keyRepeatTimers.clear()
  }

  /**
   * 销毁输入管理器
   */
  destroy(): void {
    this.disable()
    this.unbindEventListeners()
    this.clearBindings()
    this.clearHandlers()
  }
}